home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / stdwin / Ports / x11 / general.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-22  |  13.9 KB  |  555 lines  |  [TEXT/????]

  1. /* X11 STDWIN -- General initializations, enquiries and defaults */
  2.  
  3. #include "x11.h"
  4.  
  5.  
  6. /* Private globals */
  7.  
  8. Display *_wd;            /* The Display (== connection) */
  9. Screen *_ws;            /* The screen */
  10. XFontStruct *_wf;        /* The font */
  11. XFontStruct *_wmf;        /* The menu font */
  12. #ifdef PIPEHACK
  13. int _wpipe[2];            /* Pipe used by wungetevent from handler */
  14. #endif
  15. #ifdef AMOEBA
  16. #include <amoeba.h>
  17. #include <semaphore.h>
  18. extern semaphore *_wsema;    /* From amtimer.c */
  19. #endif
  20. char *_wprogname = "stdwin";    /* Program name from argv[0] */
  21. static char *_wdisplayname;    /* Display name */
  22.  
  23. /* Interned atoms */
  24.  
  25. Atom _wm_protocols;
  26. Atom _wm_delete_window;
  27. Atom _wm_take_focus;
  28.  
  29. /* Globals used to communicate hints to wopen() */
  30.  
  31. char *_whostname;
  32. char *_wm_command;
  33. int _wm_command_len;
  34.  
  35. /* Copy the arguments away to _wm_command, and get the host name */
  36.  
  37. static void
  38. storeargcargv(argc, argv)
  39.     int argc;
  40.     char **argv;
  41. {
  42.     int i;
  43.     char *bp;
  44.     char buf[256];
  45.     
  46.     /* Calculate length of buffer to allocate */
  47.     _wm_command_len= 0;
  48.     for (i= 0; i < argc; i++)
  49.         _wm_command_len += strlen(argv[i]) + 1;
  50.     if (_wm_command_len != 0) {
  51.         _wm_command= bp= malloc((unsigned)_wm_command_len);
  52.         for (i= 0; i < argc; i++) {
  53.             strcpy(bp, argv[i]);
  54.             bp += strlen(argv[i]) + 1;
  55.         }
  56.     }
  57.     
  58.     buf[0]= EOS;
  59.     gethostname(buf, sizeof buf);
  60.     buf[(sizeof buf)-1]= EOS;
  61.     _whostname= strdup(buf);
  62. }
  63.  
  64. /* Function to get a default directly from a database */
  65.  
  66. static char *
  67. getoption(db, name, classname)
  68.     XrmDatabase db;
  69.     char *name;
  70.     char *classname;
  71. {
  72.     char namebuf[256], classnamebuf[256];
  73.     char *type;
  74.     XrmValue rmvalue;
  75.     
  76.     sprintf(namebuf, "%s.%s", _wprogname, name);
  77.     sprintf(classnamebuf, "Stdwin.%s", classname);
  78.     if (XrmGetResource(db, namebuf, classnamebuf, &type, &rmvalue))
  79.         return rmvalue.addr;
  80.     else
  81.         return NULL;
  82. }
  83.  
  84. /* Command line options tables */
  85.  
  86. /* NOTE: To prevent stdwin eating user options scanned with getopt(3),
  87.    single-letter options must never be acceptable as abbreviations.
  88.    When necessary, this is ensured by adding dummy options, e.g., "-g:"
  89.    because there is only one option starting with "-g" ("-geometry").
  90.    (The colon is used as second character because getopt() uses it as a
  91.    delimiter.)
  92.    Watch out: if you remove the last option starting with a certain
  93.    letter, also remove the dummy option!
  94. */
  95.  
  96. /* Table 1: command-line only options */
  97.  
  98. static XrmOptionDescRec options1[]= {
  99.   
  100. {"-debuglevel",        ".debugLevel",        XrmoptionSepArg, NULL},
  101. {"-display",        ".display",        XrmoptionSepArg, NULL},
  102.  
  103. {"-n:",            NULL,            XrmoptionIsArg,  NULL},
  104. {"-name",        ".name",        XrmoptionSepArg, NULL},
  105.  
  106. {"-s:",            NULL,            XrmoptionIsArg,  NULL},
  107. {"-synchronous",    ".synchronous",        XrmoptionNoArg,  "on"},
  108.  
  109. };
  110.  
  111. /* Table 2: options to be merged with resources */
  112.  
  113. static XrmOptionDescRec options2[]= {
  114.  
  115. /* Command line options to override resources.
  116.    All the options named in "man X" are supported, except those to
  117.    do with borders (-bd, -bw) or national language choice (-xnl*). */
  118.  
  119. {"-background",        ".background",        XrmoptionSepArg, NULL},
  120. {"-bg",            ".background",        XrmoptionSepArg, NULL},
  121.  
  122. {"-font",        ".font",        XrmoptionSepArg, NULL},
  123. {"-fn",            ".font",        XrmoptionSepArg, NULL},
  124. {"-foreground",        ".foreground",        XrmoptionSepArg, NULL},
  125. {"-fg",            ".foreground",        XrmoptionSepArg, NULL},
  126.  
  127. {"-g:",            NULL,            XrmoptionIsArg,  NULL},
  128. {"-geometry",        ".geometry",        XrmoptionSepArg, NULL},
  129.  
  130. {"-iconic",        ".iconic",        XrmoptionNoArg,  "on"},
  131. {"-iconbitmap",        ".iconBitmap",        XrmoptionSepArg, NULL},
  132. {"-icongeometry",    ".iconGeometry",    XrmoptionSepArg, NULL},
  133. {"-iconmask",        ".iconMask",        XrmoptionSepArg, NULL},
  134.  
  135. {"-menubackground",    ".menuBackground",    XrmoptionSepArg, NULL},
  136. {"-menubg",        ".menuBackground",    XrmoptionSepArg, NULL},
  137. {"-menufont",        ".menuFont",        XrmoptionSepArg, NULL},
  138. {"-menufn",        ".menuFont",        XrmoptionSepArg, NULL},
  139. {"-menuforeground",    ".menuForeground",    XrmoptionSepArg, NULL},
  140. {"-menufg",        ".menuForeground",    XrmoptionSepArg, NULL},
  141.  
  142. {"-reversevideo",    ".reverse",        XrmoptionNoArg,  "on"},
  143. {"-rv",            ".reverse",        XrmoptionNoArg,  "on"},
  144. {"+rv",            ".reverse",        XrmoptionNoArg,  "off"},
  145.  
  146. {"-s:",            NULL,            XrmoptionIsArg,  NULL},
  147. {"-selectionTimeout",    ".selectionTimeout",    XrmoptionSepArg, NULL},
  148.  
  149. {"-t:",            NULL,            XrmoptionIsArg,  NULL},
  150. {"-title",        ".title",        XrmoptionSepArg, NULL},
  151.  
  152. {"-x:",            NULL,            XrmoptionIsArg,  NULL},
  153. {"-xrm",        NULL,            XrmoptionResArg, NULL},
  154.  
  155. /* Options that end option processing completely:
  156.    "-" means <stdin>, "--" is a getopt(3) convention
  157.    to force the end of the option list. */
  158.  
  159. {"-",            NULL,            XrmoptionSkipLine, NULL},
  160. {"--",            NULL,            XrmoptionSkipLine, NULL},
  161.  
  162. };
  163.  
  164. #define NUM(options) (sizeof options / sizeof options[0])
  165.  
  166.  
  167. /* Initialization is split in two parts -- wargs(&argc, &argv) to process
  168.    the command line, winit() to open the connection.  The call
  169.    winitargs(&argc, &argv) calls wargs() and then winit().
  170.  
  171.    Programs that call winit() without calling wargs() will always
  172.    appear to have the name "stdwin", and you can't pass X command
  173.    line arguments on their command line.  Defaults put in the server's
  174.    resource database for application name 'stdwin' will work, though.
  175.    You can also set the environment variable RESOURCE_NAME. */
  176.  
  177.  
  178. static XrmDatabase db = NULL; /* Passed between wargs() and winit() */
  179. static int wargs_called; /* Set when wargs is called */
  180.  
  181. /* Part one of the initialization -- process command line arguments */
  182.  
  183. void
  184. wargs(pargc, pargv)
  185.     int *pargc;
  186.     char ***pargv;
  187. {
  188.     char **argv= *pargv;
  189.     char *value;
  190.     
  191.     if (wargs_called)
  192.         _wfatal("wargs: called more than once");
  193.     wargs_called = 1;
  194.     
  195.     /* Get the program name (similar to basename(argv[0])) */
  196.     
  197.     if (*pargc > 0 && argv[0] != NULL && argv[0][0] != EOS) {
  198.         _wprogname= strrchr(argv[0], '/');
  199.         if (_wprogname != NULL && _wprogname[1] != EOS)
  200.             ++_wprogname;
  201.         else
  202.             _wprogname= argv[0];
  203.     }
  204.     
  205.     /* Save entire argument list for WM_COMMAND hint; plus hostname */
  206.     
  207.     storeargcargv(*pargc, argv);
  208.     
  209.     /* Get command-line-only X options */
  210.     
  211.     XrmParseCommand(&db, options1, NUM(options1),
  212.         _wprogname, pargc, *pargv);
  213.     
  214.     /* Get -debuglevel argument from temp database.
  215.        This is done first so calls to _wdebug will work. */
  216.     
  217.     if ((value= getoption(db, "debugLevel", "DebugLevel")) != NULL) {
  218.         _wtracelevel= _wdebuglevel= atoi(value);
  219. #ifndef SYSV
  220.         setlinebuf(stderr);
  221. #endif
  222.         _wwarning("wargs: -debuglevel %d", _wdebuglevel, value);
  223.     }
  224.     
  225.     /* Get -display argument from temp database */
  226.     
  227.     if ((_wdisplayname= getoption(db, "display", "Display")) != NULL)
  228.         _wdebug(1, "wargs: -display %s", _wdisplayname);
  229.     
  230.     /* Get -name argument from temp database.
  231.        This will override the command name used by _wgetdefault.
  232.        You can use this to pretend the command name is different,
  233.        so it gets its options from a different part of the defaults
  234.        database.  (Try -name xmh. :-)
  235.        If -name is not set, getenv("RESOURCE_NAME") will override
  236.        _wprogname (if non-empty). */
  237.     
  238.     if ((value= getoption(db, "name", "Name")) != NULL) {
  239.         _wdebug(1, "wargs: -name %s", value);
  240.         _wprogname= strdup(value);
  241.     }
  242.     else if ((value = getenv("RESOURCE_NAME")) != NULL && *value != '\0') {
  243.         _wdebug(1, "wargs: RESOURCE_NAME=%s", value);
  244.         _wprogname = strdup(value);
  245.     }
  246.     
  247.     /* Get the remaining command line options.
  248.        Option parsing is done in two phases so that if the user
  249.        specifies -name and -geometry, the geometry is stored under
  250.        the new name (else it won't be found by _wgetdefault later). */
  251.     
  252.     XrmParseCommand(&db, options2, NUM(options2),
  253.         _wprogname, pargc, *pargv);
  254. }
  255.  
  256.  
  257. /* Part two of the initialization -- open the display */
  258.  
  259. void
  260. winit()
  261. {
  262.     char *value;
  263.  
  264.     /* Call wargs() with dummy arguments if not already called */
  265.  
  266.     if (!wargs_called) {
  267.         static char* def_args[]= {"stdwin", (char*)NULL};
  268.         int argc= 1;
  269.         char **argv= def_args;
  270.         wargs(&argc, &argv);
  271.     }
  272.     
  273.     /* Open the display, die if we can't */
  274.     
  275.     _wd= XOpenDisplay(_wdisplayname);
  276.     if (_wd == NULL) {
  277.         _wfatal("winit: can't open display (%s)",
  278.             _wdisplayname ? _wdisplayname :
  279.             getenv("DISPLAY") ? getenv("DISPLAY") : "<none>");
  280.     }
  281.     
  282. #ifdef AMOEBA
  283.     /* Set the semaphore.  This must be done before doing anything
  284.        else with the connection. */
  285.     if (_wsema != NULL)
  286.         XamSetSema(_wd, _wsema);
  287. #endif
  288.     
  289.     /* Turn on synchronous mode if required.
  290.        This is not automatic when debuglevel is set,
  291.        since some bugs disappear in synchronous mode! */
  292.     
  293.     if (getoption(db, "synchronous", "Synchronous") != NULL)
  294.         XSynchronize(_wd, True);
  295.     
  296.     /* Call XGetDefault() once.  We don't use it to get our
  297.        defaults, since it doesn't let the caller specify the class
  298.        name for the resource requested, but the first call to it
  299.        also initializes the resources database from various sources
  300.        following conventions defined by the X toolkit, and that code
  301.        is too convoluted (and X11-version specific?) to bother to
  302.        repeat it here. */
  303.     
  304.     (void) XGetDefault(_wd, _wprogname, "unused");
  305.     
  306.     /* From now on, use _wgetdefault() exclusively to get defaults */
  307.     
  308.     /* Get the debug level again, this time from the user's
  309.        defaults database.  This value overrides only if larger. */
  310.     
  311.     value= _wgetdefault("debugLevel", "DebugLevel");
  312.     if (value != 0) {
  313.         int k= atoi(value);
  314.         if (k > _wdebuglevel) {
  315.             _wtracelevel= _wdebuglevel= k;
  316.             _wdebug(1, "winit: new debuglevel %d (%s)",
  317.                 _wdebuglevel, value);
  318.             XSynchronize(_wd, True);
  319.         }
  320.     }
  321.     
  322.     /* Merge the command line options with the defaults database.
  323.        This must be done after the call to XGetDefault (above),
  324.        otherwise XGetDefault doesn't care to load the database.
  325.        I assume that the command line options get higher priority
  326.        than the user defaults in this way. */
  327.     
  328.     XrmMergeDatabases(db, &_wd->db);
  329.     db = NULL;
  330.     
  331.     /* Get the default screen (the only one we use) */
  332.     
  333.     _ws= DefaultScreenOfDisplay(_wd);
  334.     
  335.     _wdebug(1, "server does%s save-unders",
  336.         DoesSaveUnders(_ws) ? "" : "n't do");
  337.     
  338.     /* Intern some atoms (unconditionally) */
  339.     
  340.     _wm_protocols = XInternAtom(_wd, "WM_PROTOCOLS", False);
  341.     _wm_delete_window = XInternAtom(_wd, "WM_DELETE_WINDOW", False);
  342.     _wm_take_focus = XInternAtom(_wd, "WM_TAKE_FOCUS", False);
  343.     
  344.     /* Initialize font list */
  345.     
  346.     _winitfonts();
  347.  
  348.     /* Initialize colors */
  349.  
  350.     _w_initcolors();
  351.     
  352. #ifdef PIPEHACK
  353.     /* Create the pipe used to communicate wungetevent calls
  354.        from a signal handler to wgetevent */
  355.     
  356.     if (pipe(_wpipe) != 0) {
  357.         _wwarning("winit: can't create pipe");
  358.         _wpipe[0]= _wpipe[1]= -1;
  359.     }
  360. #endif
  361. }
  362.  
  363.  
  364. /* Call both parts of the initialization together */
  365.  
  366. void
  367. winitargs(pargc, pargv)
  368.     int *pargc;
  369.     char ***pargv;
  370. {
  371.     wargs(pargc, pargv);
  372.     winit();
  373. }
  374.  
  375.  
  376. /* Return the name of the display, if known.  (X11 stdwin only.) */
  377.  
  378. char *
  379. wdisplayname()
  380. {
  381.     return _wdisplayname ? _wdisplayname : getenv("DISPLAY");
  382. }
  383.  
  384.  
  385. /* Return the connection number.  (X11 stdwin only.) */
  386.  
  387. int
  388. wconnectionnumber()
  389. {
  390.     return ConnectionNumber(_wd);
  391. }
  392.  
  393.  
  394. /* Clean up */
  395.  
  396. void
  397. wdone()
  398. {
  399.     /* This may be called when we are not initialized */
  400.     if (_wd) {
  401.         _wkillwindows();
  402.         _wkillmenus();
  403.         XFlush(_wd); /* Show possibly queued visual effects */
  404.         XCloseDisplay(_wd);
  405.         _wd = NULL;
  406.     }
  407. }
  408.  
  409. /* Flush server queue */
  410.  
  411. void
  412. wflush()
  413. {
  414.     XFlush(_wd);
  415. }
  416.  
  417.  
  418. /* Get screen size */
  419.  
  420. void
  421. wgetscrsize(pwidth, pheight)
  422.     int *pwidth, *pheight;
  423. {
  424.     *pwidth= WidthOfScreen(_ws);
  425.     *pheight= HeightOfScreen(_ws);
  426. }
  427.  
  428.  
  429. /* Get screen size in mm */
  430.  
  431. void
  432. wgetscrmm(pwidth, pheight)
  433.     int *pwidth, *pheight;
  434. {
  435.     *pwidth= WidthMMOfScreen(_ws);
  436.     *pheight= HeightMMOfScreen(_ws);
  437. }
  438.  
  439. /* Subroutine to invert a rectangle.
  440.    On a colour display, we invert all planes that have a different
  441.    value in the foreground and background pixels, thus swapping
  442.    fg anbd bg colors.
  443.    Since we can't get the fg and bg pixels from a GC without cheating
  444.    (i.e., risking future incompatibility), we depend on the fact
  445.    that the plane mask is *always* set to the XOR of the fg and bg colors.
  446.    If the bg color for the window is the same as the bg for the GC,
  447.    this means all draw operations need only be concerned with those planes.
  448. */
  449.  
  450. _winvert(d, gc, x, y, width, height)
  451.     Drawable d;
  452.     GC gc;
  453.     int x, y, width, height;
  454. {
  455.     XSetFunction(_wd, gc, GXinvert);
  456.     XFillRectangle(_wd, d, gc, x, y, width, height);
  457.     XSetFunction(_wd, gc, GXcopy);
  458. }
  459.  
  460. /* Get a default (replaces XGetDefault calls) */
  461.  
  462. #include <ctype.h>
  463.  
  464. char *
  465. _wgetdefault(name, classname)
  466.     char *name;
  467.     char *classname;
  468. {
  469.     char namebuf[256], classnamebuf[256];
  470.     register char *p;
  471.     
  472.     p = getoption(_wd->db, name, classname);
  473.     if (p != NULL)
  474.         return p;
  475.     
  476.     /* XXX Compatibility hack.  Previous versions of STDWIN used
  477.        a different resource format, where the name would be
  478.        <progname>.stdwin.<resname> and the classname was defaulted
  479.        by XGetDefault to Program.Name (or some such).
  480.        The resource names were also all lowercase. */
  481.     sprintf(namebuf, "stdwin.%s", name);
  482.     sprintf(classnamebuf, "Stdwin.%s", classname);
  483.     for (p = namebuf; *p != '\0'; p++) {
  484.         if (isupper(*p))
  485.             *p = tolower(*p);
  486.     }
  487.     _wdebug(1, "_wgetdefault(%s, %s): no luck, trying %s, %s",
  488.         name, classname, namebuf, classnamebuf);
  489.     return getoption(_wd->db, namebuf, classnamebuf);
  490. }
  491.  
  492. /* Get a Boolean default.  May be 'on' or 'off', 'true' or 'false',
  493.    '1' or '0'.  If not present, return the default value. */
  494.  
  495. int
  496. _wgetbool(name, classname, def)
  497.     char *name;
  498.     char *classname;
  499.     int def;
  500. {
  501.     register char *value;
  502.     struct flags {
  503.         char *name;
  504.         int value;
  505.     };
  506.     static struct flags flags[] = {
  507.         {"on",        1},
  508.         {"true",    1},
  509.         {"yes",        1},
  510.         {"1",        1},
  511.         
  512.         {"off",        0},
  513.         {"false",    0},
  514.         {"no",        0},
  515.         {"0",        0},
  516.         
  517.         {NULL,        0}    /* Sentinel */
  518.     };
  519.     struct flags *fp, *hit;
  520.     
  521.     value = _wgetdefault(name, classname);
  522.     if (value == NULL)
  523.         return def;
  524.     hit = NULL;
  525.     for (fp = flags; fp->name != NULL; fp++) {
  526.         if (matchname(fp->name, value)) {
  527.             if (hit != NULL)
  528.                 _wwarning(
  529.                     "ambiguous resource value for %s: %s",
  530.                     name, value);
  531.             hit = fp;
  532.         }
  533.     }
  534.     if (hit != NULL)
  535.         def = hit->value;
  536.     else
  537.         _wwarning("unknown resource value for %s: %s", name, value);
  538.     return def;
  539. }
  540.  
  541. static int
  542. matchname(fullname, shortname)
  543.     char *fullname;
  544.     char *shortname;
  545. {
  546.     register int c;
  547.     while ((c = *shortname++) != '\0') {
  548.         if (isupper(c))
  549.             c = tolower(c);
  550.         if (c != *fullname++)
  551.             return 0;
  552.     }
  553.     return 1;
  554. }
  555.